<?php

declare (strict_types = 1);

namespace App\Service\Organziation;

use App\Constants\ErrorCode;
use App\Dao\AuthAdminLogDao;
use App\Dao\AuthEmployeeDao;
use App\Dao\AuthOrganizationDao;
use App\Dao\AuthProjectEmployeeDao;
use App\Exception\BusinessException;
use App\Service\Auth\ModuleService;
use App\Utils\ApiUtils;
use Hyperf\DbConnection\Db;

class OrganziationService
{
    /**
     * 查询公司信息
     *
     * @Author czm
     * @DateTime 2020-09-29
     * @param array $params
     * @return void
     */
    function list(array $params) {
        if (isset($params['list_type']) && $params['list_type'] == 1) {
            $map = [
                ['company_id', "=", $params['company_id']],
            ];
            if (isset($params['employee_id']) && $params['employee_id']) {
                $map[] = ['employee_id', "=", $params['employee_id']];
            }
            $data = make(AuthOrganizationDao::class)->getByWhereTrait($map, ['id', 'name'])->toArray();
        } elseif (isset($params['list_type']) && $params['list_type'] == 2) {
            $data = make(AuthOrganizationDao::class)->getTreeWithPrincipal((int) $params['company_id'], 0, true);
        } elseif (isset($params['list_type']) && $params['list_type'] == 3) {
            $data = make(AuthOrganizationDao::class)->getTreeWithEmployee((int) $params['company_id']);
        } else {
            $data = make(AuthOrganizationDao::class)->getTreeWithPrincipal((int) $params['company_id']);
        }

        return ApiUtils::send(ErrorCode::SUCCESS, "操作成功", $data);
    }

    /**
     * 添加部门
     *
     * @Author czm
     * @DateTime 2020-09-29
     * @param array $params
     * @return void
     */
    public function addOrganization(array $params)
    {
        if (strpos($params['name'], '-') !== false) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '名称不能包含中划线');
        }
        $map = [
            ['name', '=', $params['name']],
            ['company_id', '=', $params['company_id']],
        ];
        if (make(AuthOrganizationDao::class)->existsByWhereTrait($map)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '公司下存在相同部门名');
        }
        $parent_org = make(AuthOrganizationDao::class)->findTrait($params['pid']);
        if (!$parent_org) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '上级部门信息错误');
        }

        $params['sort'] = make(AuthOrganizationDao::class)->countByWhereTrait(['pid' => $params['pid']]) + 1;
        $params['grade'] = $parent_org->grade + 1;
        $params['prefix_name'] = $parent_org->prefix_name . $params['name'] . "-";
        make(AuthOrganizationDao::class)->createTrait($params);
        make(AuthAdminLogDao::class)->addLog('新增部门' . json_encode($params, JSON_UNESCAPED_UNICODE));
        return ApiUtils::send(ErrorCode::SUCCESS, "操作成功");

    }

    /**
     * 编辑部门信息
     *
     * @Author czm
     * @DateTime 2020-09-29
     * @param array $params
     * @return void
     */
    public function editOrganization(array $params)
    {
        if (strpos($params['name'], '-') !== false) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '名称不能包含中划线');
        }
        $map = [
            ['name', '=', $params['name']],
            ['company_id', '=', $params['company_id']],
            ['id', '!=', $params['organization_id']],
        ];
        if (make(AuthOrganizationDao::class)->existsByWhereTrait($map)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '公司下存在相同部门名');
        }

        $parent_org = make(AuthOrganizationDao::class)->findTrait($params['pid']);

        $organiztion = make(AuthOrganizationDao::class)->findTrait($params['organization_id']);
        Db::beginTransaction();
        try {
            //修正后缀
            if ($organiztion->name != $params['name']) {
                $map = [
                    ['prefix_name', 'like', "%{$organiztion->name}-%"],
                    ['company_id', '=', $organiztion->company_id],
                ];
                $update_organiztion = make(AuthOrganizationDao::class)->getByWhereTrait($map);
                foreach ($update_organiztion as $val) {
                    if ($params['organization_id'] != $val['id']) {
                        $val['prefix_name'] = str_replace($organiztion->name . "-", $params['name'] . "-", $val['prefix_name']);
                        make(AuthOrganizationDao::class)->updateByIdTrait(['id' => $val['id'], 'prefix_name' => $val['prefix_name']]);
                    }
                }
            }
            // if ($organiztion->employee_id && $organiztion->employee_id != $params['employee_id']) {
            //     //解除负责人项目关联
            //     $project_ids = make(AuthProjectEmployeeDao::class)->searchAll([['organization_id', '=', $params['organization_id']], ['is_del', '=', 1]], ['id', 'project_id']);
            //     //去除旧负责人项目关联
            //     make(AuthProjectEmployeeDao::class)->delPrincipalByWhereIn(array_column($project_ids, 'id'));
            //     //绑定新的负责人;
            //     foreach ($project_ids as $val) {
            //         $params['employee_id'] && make(AuthProjectEmployeeDao::class)->add([
            //             'project_id' => $val['project_id'],
            //             'employee_id' => $params['employee_id'],
            //             'company_id' => $organiztion->company_id,
            //             'type' => AuthProjectEmployee::JOIN_TYPE,
            //             'organization_id' => $params['organization_id'],
            //             'add_time' => time(),
            //             'update_time' => time(),
            //         ]);
            //     }
            // }

            $params['grade'] = $parent_org['grade'] ?? 0 + 1;
            $params['prefix_name'] = $parent_org['prefix_name '] ?? '' . $params['name'] . "-";
            $params['id'] = $params['organization_id'];
            make(AuthOrganizationDao::class)->updateByIdTrait($params);
            make(AuthAdminLogDao::class)->addLog('编辑部门' . json_encode($params, JSON_UNESCAPED_UNICODE) . '原数据 ' . $organiztion->toJson(JSON_UNESCAPED_UNICODE));
            Db::commit();
            //删除部门权限缓存
            make(ModuleService::class)->clearRedisPermission(0, $params['organization_id']);
        } catch (\Throwable $t) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '网络异常 数据写入失败' . config('web.err_msg_splite') . $t->getMessage() . "行: " . $t->getLine());
        }
        return ApiUtils::send(ErrorCode::SUCCESS, "操作成功");
    }

    /**
     * 删除部门
     *
     * @Author czm
     * @DateTime 2020-09-30
     * @param array $params
     * @return void
     */
    public function delOrganization(array $params)
    {
        if (make(AuthOrganizationDao::class)->existsByWhereTrait(['pid' => $params['organization_id']])) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '存在下级无法删除');
        }

        if ($params['operation_confirm'] != 2) {
            return ApiUtils::send(ErrorCode::SUCCESS, '请确认删除', [false]);
        }
        $organiztion = make(AuthOrganizationDao::class)->findTrait($params['organization_id']);
        if ($organiztion->pid == 0) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '该部门不支持操作');
        }
        Db::beginTransaction();
        try {
            //清除关联项目
            if ($organiztion->employee_id) {
                //解除项目关联
                make(AuthProjectEmployeeDao::class)->updateByWhere([
                    ['organization_id', '=', $organiztion->id],
                    ['employee_id', '=', $organiztion->employee_id],
                ], [
                    'is_del' => 2,
                    'update_time' => time(),
                ]);
            }
            //删除部门项目关联
            // make(AuthProjectOrganizationDao::class)->delByWhereIn([], [$params['organization_id']]);
            $employee_ids = make(AuthEmployeeDao::class)->pluckByWhereTrait(['organization_id' => $params['organization_id']], 'id')->toArray();
            //把部门人挂载在上级部门
            make(AuthEmployeeDao::class)->updateByWhereTrait(['organization_id' => $params['organization_id']], ['organization_id' => $organiztion->pid]);
            $organiztion->is_del = 2;
            $organiztion->save();
            make(AuthAdminLogDao::class)->addLog('删除部门' . json_encode($params, JSON_UNESCAPED_UNICODE));
            Db::commit();
            //删除部门权限缓存
            make(ModuleService::class)->clearRedisPermission(0, $params['organization_id']);

            //刷新用户信息
            foreach ($employee_ids as $val) {
                make(EmployeeService::class)->userInfo(['employee_id' => $val]);
            }
        } catch (\Throwable $t) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '网络异常 数据写入失败' . config('web.err_msg_splite') . $t->getMessage());
        }
        return ApiUtils::send(ErrorCode::SUCCESS, "操作成功");

    }

    /**
     * 上移下移部门
     *
     * @Author czm
     * @DateTime 2020-09-30
     * @param array $params
     * @return void
     */
    public function sort(array $params)
    {
        $organiztion = make(AuthOrganizationDao::class)->findTrait($params['organization_id']);
        if ($organiztion->pid == 0) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '顶级部门操作');
        }
        if (make(AuthOrganizationDao::class)->countByWhereTrait(['pid' => $organiztion->pid]) == 1) {
            goto end;
        } else if ($params['sort_type'] == 1) {
            //上移
            $sort = $organiztion->sort - 1;
        } else {
            //下移
            $sort = $organiztion->sort + 1;
        }
        $next_organiztion = make(AuthOrganizationDao::class)->firstByWhereTrait([['pid', '=', $organiztion->pid], ['sort', '=', $sort]]);
        if (empty($next_organiztion)) {
            goto end;
        }
        Db::beginTransaction();
        try {
            $next_organiztion->sort = $organiztion->sort;
            $next_organiztion->save();
            $organiztion->sort = $sort;
            $organiztion->save();
            Db::commit();
        } catch (\Throwable $t) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '网络异常 数据写入失败' . config('web.err_msg_splite') . $t->getMessage());
        }
        end:
        return ApiUtils::send(ErrorCode::SUCCESS, "操作成功");

    }

    /**
     * 获取部门树结构
     *
     * @Author czm
     * @DateTime 2020-09-30
     * @param integer $company_id
     * @return void
     */
    public function treeList(array $params)
    {
        $company_id = $params['company_id'];
        $map = [
            ['company_id', '=', $company_id],
        ];
        $items = make(AuthOrganizationDao::class)->getByWhereTrait($map, ["id", "name", "pid", "sort"])->keyBy('id')->toArray();
        $t = function () use ($items) {
            $tree = [];
            foreach ($items as $key => $value) {
                if (isset($items[$value['pid']])) {
                    $items[$value['pid']]['_child'][] = &$items[$key];
                } else {
                    $tree[] = &$items[$key];
                }
            }
            return $tree;
        };
        //设置树形结构
        return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $t());
    }

    /**
     * 获取公司组织下关联项目
     *
     * @Author czm
     * @DateTime 2020-09-30
     * @param integer $company_id
     * @return void
     */
    // public function project(array $params)
    // {
    //     //获取部门绑定项目
    //     // $project_ids = make(AuthProjectOrganizationDao::class)->searchAll([['company_id', '=', $params['company_id']]], ['project_id']);
    //     // $project_ids = array_column($project_ids, 'project_id');
    //     $data = make(AuthProjectDao::class)->getByWhereIn([['company_id', '=', $params['company_id']], ['is_del', '=', 1], ['status', '=', AuthProject::IS_STATUS]], [], ['id', 'name']);
    //     return ApiUtils::send(ErrorCode::SUCCESS, '获取成功', $data);
    // }
}
